\defmodule {Event}

This abstract class provides event scheduling tools.
Each type of event should be defined as a subclass of the
class \texttt{Event}, and should provide an implementation of the method
\method{actions}{} which is executed when an event of this type occurs.
The instances of these subclasses are the actual events.

Each event is linked to a simulator represented by an instance of
\class{Simulator} before it can be scheduled and processed.
A default simulator, given by \texttt{Simulator.getDefaultSimulator},
is used if no simulator is linked explicitly with an event.
When an event is constructed, it is not scheduled. It must be scheduled
separately by calling one of the scheduling methods \method{schedule}{},
\method{scheduleNext}{}, \method{scheduleBefore}{}, etc.
An event can also be cancelled before it occurs.

A scheduled event has an associated time at which it will happen and a priority,
which can be queried using the methods \method{time}{} and \method{priority}{}, respectively.
By default, events occur in ascending order of time, and have priority 1.
Events with the same time occur in ascending order of priority.
For example, if events \texttt{e1} and \texttt{e2} occur at the same time
with priority 2 and 1 respectively, then \texttt{e2} will occur before \texttt{e1}.
Events with the same time and priority occur in the order they were scheduled.

\bigskip\hrule

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{code}
\begin{hide}
/*
 * Class:        Event
 * Description:  provides event scheduling tools
 * Environment:  Java
 * Software:     SSJ 
 * Copyright (C) 2001  Pierre L'Ecuyer and Universite de Montreal
 * Organization: DIRO, Universite de Montreal
 * @author       
 * @since

 * SSJ is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License (GPL) as published by the
 * Free Software Foundation, either version 3 of the License, or
 * any later version.

 * SSJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * A copy of the GNU General Public License is available at
   <a href="http://www.gnu.org/licenses">GPL licence site</a>.
 */
\end{hide}
package umontreal.iro.lecuyer.simevents;

public abstract class Event implements Comparable<Event>\begin{hide} {

   protected Simulator sim;
   //simulator linked with the current event

   protected double priority;
   //priority of the event. Priority is a second parameter (after eventTime)
   // used to class events for their running order, in the EventList.

   protected double eventTime;
   // Planned time of occurence of this event.  Negative if not planned.
   // Is protected because it is used (changed) in Process.

   // Replace that with instanceof simProcess to completely detach processes.
   // protected boolean isProcess = false;
   // Will be true for objects of the subclass Process of the class Event.
   // (i.e., true if this event is a process.)

   private int myra = 0;
   // A new event must always occur after those with same time and 
   // same priority in the Event list. myra is used for that in
   // SplayTree.java.

   // For internal use
   public final int getRa() { return myra; }
   public final void setRa(int r) { myra = r; }
\end{hide}
\end{code}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsubsection* {Constructors}

\begin{code}

   public Event() \begin{hide} {
      this (Simulator.getDefaultSimulator());
   } \end{hide}
\end{code}
   \begin{tabb} Constructs a new event instance, which can be placed afterwards
    into the event list of the default simulator\latex{ by calling one of the
    \texttt{schedule...} variants}.
    For example, if \texttt{Bang} is an \texttt{Event} subclass,
    the statement ``\texttt{new Bang().scheduleNext();}'' creates a new
    \texttt{Bang} event and places it at the beginning of the event list.
   \end{tabb}
%%%%%%%%%%
\begin{comment}
\begin{vcode}

   public Event (double delay) \begin{hide} {
      this (Simulator.getDefaultSimulator(), delay);
   } \end{hide}

   public Event (Simulator sim, double delay)\begin{hide} {
      if (sim == null)
         throw new NullPointerException();
      if (delay >= 0.0) {
         priority = 1;
         this.sim = sim;
         eventTime = sim.time() + delay;
         sim.eventList.add (this);
      }
      else
         throw new IllegalArgumentException ("Cannot schedule in the past.");
   }\end{hide}
\end{vcode}
   \begin{tabb} Constructs a new event and inserts it in the event
     list of the default simulator.
    If \texttt{delay >= 0.0}, the event is scheduled to happen in
    \texttt{delay} units of simutated time.
    If two or more events are scheduled to happen at the same time,
    events with the highest priorities (lowest value of the
    \texttt{priority}
    field) occur first.  If two or more events are schedule to the
    same time, with the same priority,
    they are placed in the event list (and executed) in the same order
    as they have been scheduled.

   We recall that such constructors with parameters are not inherited
   automatically by the subclasses in Java, but they can be invoked
   using \texttt{super}. For example, one can have
\begin{vcode}
   class Bang extends Event {
      public Bang (double delay) { super (delay); }
      public void actions() {  \dots  }
\end{vcode}
   and then invoke the constructor ``\texttt{new Bang (10.0)}'' to get
   a \texttt{Bang} in 10 units of time.
   This is equivalent to ``\texttt{new Bang().schedule(10.0)}.''
  \end{tabb}
\begin{htmlonly}
   \param{delay}{simulation time that must pass before the event happens}
\end{htmlonly}
\end{comment}
\begin{code}

   public Event (Simulator sim) \begin{hide} {
      if (sim == null)
         throw new NullPointerException();
      eventTime = -10.0;
      priority = 1.0;
      this.sim = sim;
   } \end{hide}
\end{code}
  \begin{tabb} Construct a new event instance associated with the given simulator.
  \end{tabb}
\begin{htmlonly}
   \param{sim}{Instance of class Simulator associated with the new Event}
\end{htmlonly}
%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsubsection* {Methods}

\begin{code}

   public void schedule (double delay) \begin{hide} {
      if (delay < 0.0)
         throw new IllegalArgumentException ("Cannot schedule in the past.");
      if (eventTime > -1.0)
         throw new IllegalStateException ("Event already scheduled");
      eventTime = sim.time() + delay;
      sim.eventList.add (this);
   } \end{hide}
\end{code}
  \begin{tabb} Schedules this event to happen in \texttt{delay} time units,
   i.e., at time \texttt{sim.time() + delay}, by inserting it in the event list.
   When two or more events are scheduled to happen at the same time and
    with the same priority,
   they are placed in the event list (and executed) in the same order
   as they have been scheduled.
   Note that the priority of this event should be adjusted using
   \method{setPriority}{} \emph{before} it is scheduled.
  \end{tabb}
\begin{htmlonly}
   \param{delay}{simulation time that must pass before the event happens}
\end{htmlonly}
\begin{code}

   public void scheduleNext() \begin{hide} {
      if (eventTime > -1.0)
         throw new IllegalStateException ("Event already scheduled");
      eventTime = sim.time();
      priority  = 0.0;
      sim.eventList.addFirst (this);
   } \end{hide}
\end{code}
  \begin{tabb}  Schedules this event as the {\em first\/} event in the event
   list, to be executed at the current time (as the next event).
  \end{tabb}
\begin{code}

   public void scheduleBefore (Event other) \begin{hide} {
      if (eventTime > -1.0)
         throw new IllegalStateException ("Event already scheduled");
      eventTime = other.eventTime;
      priority = other.priority;
      sim.eventList.addBefore (this, other);
   } \end{hide}
\end{code}
  \begin{tabb}  Schedules this event to happen just before, and at the same
   time, as the event \texttt{other}.
    For example, if \texttt{Bing} and \texttt{Bang} are \texttt{Event}
     subclasses, after the statements
    \begin{vcode}

         Bang bigOne = new Bang().schedule(12.0);
         new Bing().scheduleBefore(bigOne);
   \end{vcode}
    the event list contains two new events scheduled to happen in 12
    units of time: a \texttt{Bing} event, followed by a \texttt{Bang} called
    \texttt{bigOne}.
  \end{tabb}
\begin{htmlonly}
   \param{other}{event before which this event will be scheduled}
\end{htmlonly}
\begin{code}

   public void scheduleAfter (Event other) \begin{hide} {
      if (eventTime > -1.0)
         throw new IllegalStateException ("Event already scheduled");
      eventTime = other.eventTime;
      priority = other.priority;
      sim.eventList.addAfter (this, other);
   } \end{hide}
\end{code}
  \begin{tabb} Schedules this event to happen just after, and at the same
   time, as the event \texttt{other}.
  \end{tabb}
\begin{htmlonly}
   \param{other}{event after which this event will be scheduled}
\end{htmlonly}
\begin{code}

   public void reschedule (double delay) \begin{hide} {
      if (delay < 0.0)
         throw new IllegalArgumentException ("Cannot schedule in the past.");
      if (eventTime < -1.0)
         throw new IllegalStateException ("Event not scheduled");
      sim.getEventList().remove (this);
      eventTime = sim.time() + delay;
      sim.getEventList().add (this);
   } \end{hide}
\end{code}
  \begin{tabb} Cancels this event and reschedules it to happen
   in \texttt{delay} time units.
  \end{tabb}
\begin{htmlonly}
   \param{delay}{simulation time units that must elapse before the event happens}
\end{htmlonly}
\begin{code}

   public boolean cancel() \begin{hide} {
      boolean removed = false;
      if (eventTime >= sim.time()) removed = sim.getEventList().remove (this);
      eventTime = -10.0;
      return removed;
   } \end{hide}
\end{code}
  \begin{tabb}  Cancels this event before it occurs.
   Returns \texttt{true} if cancellation succeeds (this event was found
   in the event list), \texttt{false} otherwise.
  \end{tabb}
\begin{htmlonly}
   \return{\texttt{true} if the event could be cancelled}
\end{htmlonly}
\begin{code}

   public final boolean cancel (String type) \begin{hide} {
      Event ev = sim.getEventList().getFirstOfClass (type);
      return ev.cancel();
   } \end{hide}
\end{code}
  \begin{tabb}  Finds the first occurence of an event of class ``type''
    in the event list, and cancels it.
    Returns \texttt{true} if cancellation succeeds, \texttt{false} otherwise.
  \end{tabb}
\begin{htmlonly}
   \param{type}{name of an event subclass}
   \return{\texttt{true} if an event of this class was found and cancelled}
\end{htmlonly}
\begin{code}

   public final Simulator simulator() \begin{hide} {
      return sim;
   } \end{hide}
\end{code}
  \begin{tabb}  Returns the simulator linked to this event.
  \end{tabb}
\begin{htmlonly}
   \return{the simulator linked to the event}
\end{htmlonly}
\begin{code}

   public final void setSimulator (Simulator sim) \begin{hide} {
      if (sim == null)
          throw new NullPointerException();
      if (eventTime > -1.0)
         throw new UnsupportedOperationException (
            "Unable to set Simulator, current Event already scheduled");
      this.sim = sim;
   } \end{hide}
\end{code}
  \begin{tabb}  Sets the simulator associated with this event to
    \texttt{sim}.
    This method should not be called while this event is in an event list.
  \end{tabb}
\begin{htmlonly}
   \param{sim}{the Simulator}
\end{htmlonly}
\begin{code}

   public final double time() \begin{hide} {
      return eventTime;
   } \end{hide}
\end{code}
  \begin{tabb}  Returns the (planned) time of occurence of this event.
  \end{tabb}
\begin{htmlonly}
   \return{the time of occurence of the event}
\end{htmlonly}
\begin{code}

   public final void setTime (double time) \begin{hide} {
      if (eventTime > -1.0)
         throw new UnsupportedOperationException(
            "Unable to set time, current Event already scheduled");
      eventTime = time;
   } \end{hide}
\end{code}
  \begin{tabb}  Sets the (planned) time of occurence of this event to \texttt{time}.
   This method should never be called after the event was scheduled, otherwise
   the events would not execute in ascending time order anymore.
  \end{tabb}
\heric{This is used internally by the event lists but it could be avoided
  because the event time is updated in the Event class.  Actually, the event
  time is set twice.
  It is also used in simprocs because some special (negative) values
  of event time mark process states.  If we want to remove setTime,
  we would have to implement a different mechanism (e.g., a new variable in
   simProcess) to maintain the process state.}
\begin{htmlonly}
   \param{time}{new time of occurence for the event}
\end{htmlonly}
\begin{code}

   public final double priority() \begin{hide} {
      return priority;
   } \end{hide}
\end{code}
  \begin{tabb}  Returns the priority of this event.
  \end{tabb}
\begin{htmlonly}
   \return{the priority of the event}
\end{htmlonly}
\begin{code}

   public final void setPriority (double priority) \begin{hide} {
      if(eventTime > -1.0)
         throw new UnsupportedOperationException(
            "Unable to set priority, current Event already scheduled");
      this.priority = priority;
   } \end{hide}
\end{code}
  \begin{tabb}  Sets the priority of this event to \texttt{inPriority}.
   This method should never be called after the event was scheduled, otherwise
   the events would not execute in ascending priority order anymore.
  \end{tabb}
\begin{htmlonly}
   \param{priority}{new priority for the event}
\end{htmlonly}
\begin{code}

   public int compareTo (Event e) \begin{hide} {
      if (eventTime < e.time())
         return -1;
      if (eventTime > e.time())
         return 1;
      // Si le moment de declenchement des "Event" est identique, on
      // examine leurs priorites.
      if (priority < e.priority())
         return -1;
      if (priority > e.priority())
         return 1;
      return 0;
   } \end{hide}
\end{code}
\begin{tabb} Compares this object with the specified object \texttt{e} for
order. Returns $-1$ or $+1$ as this event occurs before or after the specified
event \texttt{e}, respectively. If the two events occur at the same time, then
returns $-1$, $0$, or $+1$ as this event has a smaller, equal, or larger
priority than event \texttt{e}.
\end{tabb}
\begin{code}

   public abstract void actions();
\end{code}
  \begin{tabb}  This is the method that is executed when this event occurs.
   Every subclass of \texttt{Event} that is to be instantiated must provide
   an implementation of this method.
  \end{tabb}
\begin{code}\begin{hide}
}
\end{hide}
\end{code}
